<?php
namespace App\Handlers;

use App\Services\Api\ApiService;
use App\Services\Api\BulletSwooleService;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;

class BulletSwooleHandler
{
    protected $serv;
    public function __construct($serv)
    {
        $this->serv = $serv;
    }

    /**
     * websocket返回数组
     * @param string $msg
     * @param int $code
     * @param string $data
     * @method responseData
     * @author chengzhigang<1256699215@qq.com>
     */
    private function responseData($msg = "", $code = 2, $data = [])
    {
        $result = array(
            'code' => $code,
            'msg' => $msg,
            'data' => $data,
            'time' => date('Y-m-d H:i:s'),
        );
        return json_encode($result);
    }

    /**
     * websocket握手
     * @method onHandshake
     * @author chengzhigang<1256699215@qq.com>
     */
    public function onHandshake(\swoole_http_request $request, \swoole_http_response $response)
    {
        $SecWebSocketProtocol = config('const.sec_websocket_protocol');
        if (!isset($request->header['sec-websocket-protocol']) || $request->header['sec-websocket-protocol'] != $SecWebSocketProtocol) {
            $response->end('非法连接');
            return false;
        }
        // websocket握手连接算法验证
        $secWebSocketKey = $request->header['sec-websocket-key'];
        $patten = '#^[+/0-9A-Za-z]{21}[AQgw]==$#';
        if (0 === preg_match($patten, $secWebSocketKey) || 16 !== strlen(base64_decode($secWebSocketKey))) {
            $response->end();
            return false;
        }
        $key = base64_encode(
            sha1(
                $request->header['sec-websocket-key'] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
                true
            )
        );
        $headers = [
            'Upgrade' => 'websocket',
            'Connection' => 'Upgrade',
            'Sec-WebSocket-Accept' => $key,
            'Sec-WebSocket-Version' => '13',
        ];
        // WebSocket connection to 'ws://127.0.0.1:9502/'
        // failed: Error during WebSocket handshake:
        // Response must not include 'Sec-WebSocket-Protocol' header if not present in request: websocket
        if (isset($request->header['sec-websocket-protocol'])) {
            $headers['Sec-WebSocket-Protocol'] = $request->header['sec-websocket-protocol'];
        }
        foreach ($headers as $key => $val) {
            $response->header($key, $val);
        }
        $response->status(101);
        $response->end();
        $this->onOpen($this->serv, $request); //执行open方法
        return true;
    }

    /**
     * 建立连接
     * @method onOpen
     * @author chengzhigang<1256699215@qq.com>
     */
    public function onOpen($serv, $request)
    {
         $websocket = new BulletSwooleService();
         $result = $websocket->onOpen($serv, $request);
         if ($result['status'] == 2) {
             $serv->push($request->fd, $this->responseData($result['msg']));
             $this->DisConnect($serv, $request->fd, $result['msg']);
         } else {
            $serv->push($request->fd, $this->responseData($result['msg'], 1,$result['data']));
         }
    }

    public function onMessage($serv, $frame)
    {
        $websocket = new BulletSwooleService();
        $result = $websocket->onMessage($serv, $frame);
        if($result['status']==1){
            foreach ($serv->connections as $fd) {
                $connectionInfo = $serv->connection_info($fd);
                if ($connectionInfo['websocket_status'] == 3) {
                    $serv->push($fd, $this->responseData($result['msg'], 1, $result['data']));
                }
            }
        }else{
            $serv->push($frame->fd, $this->responseData($result['msg']));
            $this->DisConnect($serv, $frame->fd, $result['msg']);
        }
    }

    public function onClose($serv, $fd)
    {
        $websocket = new BulletSwooleService();
        $websocket->onClose($serv, $fd);
    }

    public function onRequest($request, $response)
    {
        $websocket = new BulletSwooleService();
        $websocket->onRequest($request, $response);
    }

    /**
     * 服务端主动关闭连接
     * @param [type] $serv
     * @param [type] $fd
     * @param [type] $msg
     * @method DisConnect
     * @author chengzhigang<1256699215@qq.com>
     */
    private function DisConnect($serv, $fd, $msg)
    {
        $serv->disconnect($fd, 3000, $msg);
    }


}
